{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](https://europe-west1-atp-views-tracker.cloudfunctions.net/working-analytics?notebook=tutorials--agent-with-streamlit-ui--building-chatbot-notebook)\n",
    "\n",
    "# Building a Chatbot AI Agent with OpenAI and Streamlit\n",
    "\n",
    "## Introduction\n",
    "\n",
    "Have you ever wanted to create your own chatbot like ChatGPT? In this tutorial, we will build a simple AI chatbot from scratch using OpenAI's API (which provides powerful language models like GPT-3.5) and Streamlit (a Python library for creating web apps).\n",
    "\n",
    "By the end, you'll have a beginner-friendly chatbot that runs in your browser, with a chat interface for conversations and a file uploader for sharing files with the bot. We'll go step-by-step, explaining every part of the code so even absolute beginners can follow along.\n",
    "\n",
    "**What we'll build:**\n",
    "- A web application where you can type messages to an AI agent and receive responses\n",
    "- The interface will resemble a chat window (like messaging apps)\n",
    "- An option to upload a file (for example, a text file) that your chatbot could potentially use\n",
    "\n",
    "The focus of this guide is on using Streamlit to create a clean and simple UI and integrating it with OpenAI's API to handle the chatbot's intelligence. Let's get started!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Requirements\n",
    "\n",
    "Before coding, make sure you have the following:\n",
    "\n",
    "- Python 3.x installed on your system\n",
    "- An OpenAI API key (required to access OpenAI's language model). You can get one by creating an account on OpenAI's website and generating an API key\n",
    "- Basic knowledge of Python (functions, variables) – we will explain everything, but it helps to understand simple Python syntax\n",
    "- Libraries: We'll use the `openai` library to communicate with OpenAI's API, and `streamlit` to build the web interface"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Installing the Required Libraries\n",
    "\n",
    "We can install the necessary libraries using pip. Run the following in a terminal/command prompt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install openai streamlit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, if you need additional libraries for file processing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install streamlit openai requests PyPDF2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup: OpenAI API Key\n",
    "\n",
    "To use OpenAI's API, you need to provide your API key so that the library can authenticate. There are a couple of ways to do this:\n",
    "\n",
    "1. **Option 1 (Recommended)**: Set the API key as an environment variable on your system (e.g., `OPENAI_API_KEY`). This keeps the key out of your code.\n",
    "   - On Linux/Mac: `export OPENAI_API_KEY='your_key_here'` in your terminal\n",
    "   - On Windows: `set OPENAI_API_KEY=\"your_key_here\"` in the Command Prompt\n",
    "\n",
    "2. **Option 2**: Directly assign the API key in your code (quick for testing, but be careful not to expose your key if you share your code)\n",
    "\n",
    "In this tutorial, we'll assume you saved your key as an environment variable for safety. It's a best practice to avoid hard-coding secrets."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "to support option #1 we should install the python-dotenv package"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting python-dotenv\n",
      "  Using cached python_dotenv-1.1.0-py3-none-any.whl.metadata (24 kB)\n",
      "Using cached python_dotenv-1.1.0-py3-none-any.whl (20 kB)\n",
      "Installing collected packages: python-dotenv\n",
      "Successfully installed python-dotenv-1.1.0\n"
     ]
    }
   ],
   "source": [
    "!pip install python-dotenv \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building the AI Agent (OpenAI Integration)\n",
    "\n",
    "First, let's write a small Python snippet to interact with OpenAI's API. This will form the brain of our chatbot – it sends the user's message to OpenAI and gets a response."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello! I'm just a computer program, so I don't have feelings, but I'm here and ready to help you. How can I assist you today?\n"
     ]
    }
   ],
   "source": [
    "from dotenv import load_dotenv\n",
    "import openai\n",
    "import os\n",
    "\n",
    "load_dotenv()  # Load environment variables from .env\n",
    "\n",
    "client = openai.OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n",
    "# If you didn't set an environment variable, you could do:\n",
    "# client = openai.OpenAI(api_key=\"sk-your-api-key\")  # (Not recommended to hard-code in real apps)\n",
    "\n",
    "# Define a function to generate a response from the AI given a user message\n",
    "def generate_response(user_prompt):\n",
    "    \"\"\"\n",
    "    Sends the user prompt to OpenAI and returns the AI's response.\n",
    "\n",
    "    Parameters:\n",
    "    -----------\n",
    "    user_prompt : str\n",
    "        The input message from the user.\n",
    "\n",
    "    Returns:\n",
    "    --------\n",
    "    str\n",
    "        The AI-generated response as plain text.\n",
    "    \"\"\"\n",
    "    # Use OpenAI's chat completion endpoint to get a chat-based response\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"gpt-4o\",  # The AI model to use\n",
    "        messages=[{\"role\": \"user\", \"content\": user_prompt}]  # The conversation context\n",
    "    )\n",
    "    # Extract the assistant's message from the response\n",
    "    message_text = response.choices[0].message.content\n",
    "    return message_text  # Return the assistant's reply\n",
    "\n",
    "# Quick test: let's see if the function works by asking a sample question\n",
    "test_reply = generate_response(\"Hello, how are you?\")\n",
    "print(test_reply)  # This should print an AI-generated response, e.g., \"Hello! I'm doing well, how can I assist you?\"\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's break down what's happening in `generate_response`:\n",
    "\n",
    "- We call `openai.Chat.completion.create(...)` with the model and a list of messages. The `messages` parameter expects a conversation history. We provide one message – the user's prompt – and specify its role as \"user\". You can also include a \"system\" message to prime the AI's behavior (for example, telling it to act as a friendly assistant), but we'll keep it simple for now.\n",
    "- We chose the model \"gpt-4o\" which is the same model behind ChatGPT and is suitable for chat interactions.\n",
    "- The OpenAI API returns a response object that contains the AI's reply. The actual text of the reply is nested inside `response[\"choices\"][0][\"message\"][\"content\"]`. We extract that and return it.\n",
    "- The `print(test_reply)` line is just to verify that everything is working. It will print the AI's answer to \"Hello, how are you?\" in the console. When running as a Streamlit app, we won't use print; this is just a sanity check.\n",
    "\n",
    "At this point, if you run this code in a regular Python environment (replacing the test prompt as needed and ensuring your API key is set), you should see a text response from the AI. This confirms our OpenAI integration works. Now that the AI agent part is ready, let's build the web interface using Streamlit."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building the Streamlit UI\n",
    "\n",
    "Streamlit makes it easy to create an interactive web interface with just Python code – no need to write HTML or JavaScript. We will create a chat-like interface where:\n",
    "\n",
    "- The page has a title and a clean layout\n",
    "- There's a sidebar with a file uploader widget (so users can upload a file, e.g., a text or PDF file)\n",
    "- The main area displays the conversation (user and assistant messages)\n",
    "- An input box at the bottom allows the user to type new messages\n",
    "\n",
    "Let's go step by step."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Setting up the Streamlit app layout\n",
    "\n",
    "We'll start by initializing the Streamlit app configuration, and adding a title at the top of the app."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import streamlit as st  # Import Streamlit for the UI\n",
    "\n",
    "# Set the configuration of the page\n",
    "st.set_page_config(\n",
    "    page_title=\"AI Chatbot\",   # Title of the web page\n",
    "    page_icon=\"🤖\",           # An icon for the page (emoji of a robot)\n",
    "    layout=\"wide\"             # Use the full width of the page for a wide layout\n",
    ")\n",
    "\n",
    "# Add a title to the app\n",
    "st.title(\"🤖 AI Chatbot Assistant\")\n",
    "st.markdown(\"**Welcome!** Ask anything or upload a file for the bot to analyze.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Explanation:\n",
    "- `st.set_page_config(...)` sets some global settings for the app. We give our app a title that will appear on the browser tab, an emoji icon (a robot face), and specify the layout as \"wide\" so the chat can use more horizontal space.\n",
    "- `st.title(\"...\")` displays a large heading at the top of the app. We included an emoji in the title as well just for style.\n",
    "- `st.markdown(\"**Welcome!** ...\")` adds a brief instruction or welcome message in bold. We use Markdown here to make the text bold."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Adding a File Uploader\n",
    "\n",
    "Next, we'll add a file uploader component. This allows users to upload a file (like a text document) that the chatbot might use. We will put the uploader in the sidebar to keep the main interface clean."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sidebar section for file upload\n",
    "uploaded_file = st.sidebar.file_uploader(\n",
    "    \"Upload a file (optional):\",  # Label for the uploader\n",
    "    type=[\"txt\", \"pdf\"]           # Limit file types to text or PDF for this example\n",
    ")\n",
    "\n",
    "# If a file is uploaded, we can read or process it (here we just show the file name for confirmation)\n",
    "if uploaded_file is not None:\n",
    "    file_details = f\"**{uploaded_file.name}** ({uploaded_file.size} bytes)\"\n",
    "    st.sidebar.write(\"Uploaded file:\", file_details)\n",
    "    # In a real app, you might pass this file's content to the AI or do something with it.\n",
    "    # For example, if it's a text file you could do: text = uploaded_file.read().decode('utf-8')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Explanation:\n",
    "- `st.sidebar.file_uploader(...)` creates a file uploader widget in the sidebar. The `type` parameter restricts the allowed file extensions (here .txt and .pdf for example purposes).\n",
    "- We check `if uploaded_file is not None:` to see if the user has uploaded something. If a file is there, we retrieve some details:\n",
    "  - `uploaded_file.name` gives the filename.\n",
    "  - `uploaded_file.size` gives the file size in bytes.\n",
    "- We display the file name and size in the sidebar using `st.sidebar.write`. We format the name in bold with Markdown.\n",
    "\n",
    "Note: The sidebar in Streamlit can be shown or hidden by the user. If you run the app and don't see the uploader, look for a small arrow or the sidebar toggler on the page to expand it."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Maintaining Chat History with Session State\n",
    "\n",
    "One important aspect of a chat interface is remembering the conversation. We want the app to show previous messages and replies, not just the latest one. Streamlit apps rerun the script from top to bottom on each user interaction, so without storing state, we'd lose the conversation history on each new message. To handle this, we use Streamlit's session state to store the messages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize chat history in session state if not already there\n",
    "if \"messages\" not in st.session_state:\n",
    "    st.session_state.messages = []  # list to hold all messages (dicts with 'role' and 'content')\n",
    "\n",
    "# (Optional) If we want the bot to start with a greeting message, we can add an initial assistant message:\n",
    "if not st.session_state.messages:\n",
    "    st.session_state.messages.append({\"role\": \"assistant\", \"content\": \"Hello! I'm here to help. Feel free to ask me anything or upload a file for analysis.\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Explanation:\n",
    "- We use a key \"messages\" in `st.session_state` to hold the conversation. The first time the app runs, this key won't exist, so we initialize it to an empty list.\n",
    "- The list `st.session_state.messages` will store messages as dictionaries like `{\"role\": \"user\", \"content\": \"Hello\"}` or `{\"role\": \"assistant\", \"content\": \"Hi, how can I help?\"}`. We will append to this list as the conversation grows.\n",
    "- We included an optional step: if the messages list is empty (meaning no conversation yet), we append a greeting from the assistant. This way, when the user opens the app, they immediately see a welcome message from the chatbot.\n",
    "\n",
    "Using session state in this way allows the app to remember past messages. Each time the script runs (for each new user input), it will retain `st.session_state.messages` from previous runs."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Displaying the Conversation\n",
    "\n",
    "Now that we have a list of messages in state, we want to display them on the page in a chat-like format. Streamlit provides `st.chat_message` for this purpose, which is perfect for showing a chat bubble with either user or assistant style formatting."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display all past messages in the chat\n",
    "for msg in st.session_state.messages:\n",
    "    if msg[\"role\"] == \"assistant\":\n",
    "        # Display assistant messages on the left (default)\n",
    "        with st.chat_message(\"assistant\"):\n",
    "            st.markdown(msg[\"content\"])\n",
    "    else:\n",
    "        # Display user messages on the right side\n",
    "        with st.chat_message(\"user\"):\n",
    "            st.markdown(msg[\"content\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Explanation:\n",
    "- We loop through each message in the messages list.\n",
    "- For each message, we check its \"role\". If the role is \"assistant\", we create a chat message container with `st.chat_message(\"assistant\")`. If the role is \"user\", we use `st.chat_message(\"user\")`.\n",
    "- Using `with st.chat_message(<role>):` opens a container styled as a chat bubble for that role. Inside that with block, we output the message content. We use `st.markdown` to render the text.\n",
    "- Streamlit automatically styles \"assistant\" messages differently from \"user\" messages (for example, different background color, and user messages might be right-aligned).\n",
    "\n",
    "After this loop runs, the app will have rendered all previous messages in order. So the user can scroll up and see the conversation history."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Sending New Messages (Chat Input)\n",
    "\n",
    "Finally, we need an input box for the user to type new messages. Streamlit's `st.chat_input()` provides a text input field fixed at the bottom of the page, which is perfect for chat apps. When the user enters a message and hits Enter, we will:\n",
    "\n",
    "1. Capture that message\n",
    "2. Add it to the session state history\n",
    "3. Send it to the OpenAI API (using our `generate_response` function from earlier)\n",
    "4. Get the AI's reply and add that to the history\n",
    "\n",
    "The app will then rerun and display the updated conversation (including the new messages) in the loop we wrote above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Chat input widget (appears at the bottom of the page)\n",
    "user_message = st.chat_input(\"Type your message here...\")\n",
    "\n",
    "if user_message:\n",
    "    # 1. Add the user message to chat history\n",
    "    st.session_state.messages.append({\"role\": \"user\", \"content\": user_message})\n",
    "    \n",
    "    # 2. Display the user message immediately (so it appears in the chat above)\n",
    "    with st.chat_message(\"user\"):\n",
    "        st.markdown(user_message)\n",
    "    \n",
    "    # 3. Generate the AI's response (this might take a moment)\n",
    "    with st.chat_message(\"assistant\"):\n",
    "        with st.spinner(\"Thinking...\"):  # Show a spinner while waiting for the AI\n",
    "            assistant_reply = generate_response(user_message)\n",
    "            st.markdown(assistant_reply)\n",
    "    # 4. Add the assistant's reply to the chat history\n",
    "    st.session_state.messages.append({\"role\": \"assistant\", \"content\": assistant_reply})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Explanation:\n",
    "- `user_message = st.chat_input(\"Type your message here...\")` creates a text input at the bottom. When the user submits a message, `st.chat_input` returns that message as a string.\n",
    "- We check `if user_message:` which will be true if the user just sent a message.\n",
    "- We then go through the steps:\n",
    "  1. Append the user's message to the messages history list with role \"user\".\n",
    "  2. Immediately display the user message in the chat. We do this so the user sees their message appear right away in the interface.\n",
    "  3. To get the AI's response, we open an `st.chat_message(\"assistant\")` context for the incoming reply. Within that, we use `st.spinner(\"Thinking...\")` to show a loading spinner while the API call is in progress. We call `generate_response(user_message)` to get the AI's answer, then display it.\n",
    "  4. We append the assistant's reply to the messages history list, with role \"assistant\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Complete Code\n",
    "\n",
    "Here's the full code combining all the snippets above into a single script:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# app.py (full code combining all steps)\n",
    "\n",
    "import os\n",
    "import openai\n",
    "import streamlit as st\n",
    "\n",
    "openai.api_key = os.getenv(\"OPENAI_API_KEY\")\n",
    "\n",
    "def generate_response(user_prompt):\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=\"gpt-4o-turbo\",\n",
    "        messages=[{\"role\": \"user\", \"content\": user_prompt}]\n",
    "    )\n",
    "    message_text = response[\"choices\"][0][\"message\"][\"content\"]\n",
    "    return message_text\n",
    "\n",
    "st.set_page_config(page_title=\"AI Chatbot\", page_icon=\"🤖\", layout=\"wide\")\n",
    "st.title(\"🤖 AI Chatbot Assistant\")\n",
    "st.markdown(\"**Welcome!** Ask anything or upload a file for the bot to analyze.\")\n",
    "\n",
    "uploaded_file = st.sidebar.file_uploader(\"Upload a file (optional):\", type=[\"txt\", \"pdf\"])\n",
    "if uploaded_file is not None:\n",
    "    st.sidebar.write(\"Uploaded file:\", f\"**{uploaded_file.name}** ({uploaded_file.size} bytes)\")\n",
    "\n",
    "if \"messages\" not in st.session_state:\n",
    "    st.session_state.messages = []\n",
    "if not st.session_state.messages:\n",
    "    st.session_state.messages.append({\"role\": \"assistant\", \"content\": \"Hello! I'm here to help. Feel free to ask me anything or upload a file.\"})\n",
    "\n",
    "# Display existing chat messages\n",
    "for msg in st.session_state.messages:\n",
    "    with st.chat_message(msg[\"role\"]):\n",
    "        st.markdown(msg[\"content\"])\n",
    "\n",
    "# Chat input widget for new messages\n",
    "if user_msg := st.chat_input(\"Type your message here...\"):\n",
    "    # Add user message to history and display it\n",
    "    st.session_state.messages.append({\"role\": \"user\", \"content\": user_msg})\n",
    "    with st.chat_message(\"user\"):\n",
    "        st.markdown(user_msg)\n",
    "    # Generate assistant response with spinner\n",
    "    with st.chat_message(\"assistant\"):\n",
    "        with st.spinner(\"Thinking...\"):\n",
    "            assistant_msg = generate_response(user_msg)\n",
    "            st.markdown(assistant_msg)\n",
    "    # Add assistant response to history\n",
    "    st.session_state.messages.append({\"role\": \"assistant\", \"content\": assistant_msg})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running the App\n",
    "\n",
    "Now that we have the code (for example, in a file named app.py), we can run the Streamlit app. In a terminal, make sure you are in the directory containing app.py and run:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run this in your terminal, not in this notebook\n",
    "# streamlit run app.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This command will launch the Streamlit development server and open a web browser to the app (usually at http://localhost:8501). You should see your chatbot interface with the title and an initial greeting from the assistant.\n",
    "\n",
    "Try it out: type a question into the chat box (for example, \"What is the capital of France?\") and hit Enter. You should see your message appear on the right, and after a moment, the AI's response will appear on the left (the app might show \"Thinking...\" while waiting for the response).\n",
    "\n",
    "Note: Ensure your OpenAI API key is valid and you have internet access when running the app, because the app needs to call OpenAI's servers to get responses."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Streamlit Chatbot Interface\n",
    "# \n",
    "##### Here's what your chatbot interface should look like when running:\n",
    "# \n",
    "# ![Streamlit Chatbot Interface](assets/streamlit_chatbot.png)\n",
    "# \n",
    "##### This shows the chat interface with message history, input box at the bottom, and the file upload option in the sidebar.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Streamlit Chatbot Demo\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<video width=\"960\" height=\"720\" controls>\n",
       "  <source src=\"assets/streamlit_chatbot_video.mp4\" type=\"video/mp4\">\n",
       "  Your browser does not support the video tag.\n",
       "</video>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "\n",
    "HTML(\"\"\"\n",
    "<video width=\"960\" height=\"720\" controls>\n",
    "  <source src=\"assets/streamlit_chatbot_video.mp4\" type=\"video/mp4\">\n",
    "  Your browser does not support the video tag.\n",
    "</video>\n",
    "\"\"\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " ##### This video shows how users can interact with the chatbot in real-time, ask questions, and receive responses."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "Congratulations on building your first AI chatbot with Streamlit and OpenAI! 🎉 In this tutorial, we covered:\n",
    "\n",
    "- Installing and setting up the necessary libraries (streamlit and openai)\n",
    "- Obtaining and using an OpenAI API key to access a GPT-4o model\n",
    "- Writing a function to communicate with the OpenAI API and get responses\n",
    "- Using Streamlit to create a web interface, including a chat message display and input box, as well as a file uploader in the sidebar\n",
    "- Maintaining state (conversation history) across interactions using st.session_state, enabling a multi-turn conversation\n",
    "- Running the Streamlit app and interacting with the chatbot through your browser\n",
    "\n",
    "This basic app provides a foundation that you can extend in many ways:\n",
    "\n",
    "- **Improve the AI's context**: We kept the AI calls stateless (only sending the latest user prompt). You could send the whole conversation in the messages to ChatCompletion.create so the AI remembers previous questions.\n",
    "- **Use the uploaded file**: Integrate the file content into the conversation. For example, if a PDF is uploaded, extract its text and prepend it as a system message.\n",
    "- **UI enhancements**: Streamlit's chat elements support things like avatars and you can add more design elements (colors, sidebar info, etc.).\n",
    "- **Deployment**: You can easily deploy this app to the web (for example, using Streamlit Cloud) and share your chatbot with friends or colleagues.\n",
    "\n",
    "With relatively few lines of code, we created an interactive AI assistant! Feel free to experiment and build on this. Happy coding, and enjoy chatting with your new AI chatbot! 🚀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
